package sany.iec.service.schedule;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import sany.iec.config.GlobalVariable;
import sany.iec.entity.DataEntity;
import sany.iec.entity.ServerEntity;
import sany.iec.enums.DataCategoryEnum;
import sany.iec.enums.EnableEnum;
import sany.iec.enums.ModbusRegisterEnum;
import sany.iec.enums.ServerType;
import sany.iec.service.IEC104ServerService;
import sany.iec.service.ModbusServerService;
import sany.iec.utils.FormulaCalculationUtil;

import javax.annotation.Resource;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Author : 托马斯
 * @Date : 2025/7/7 16:31
 * @Description :
 */
@Service
@Slf4j
public class DataUpdateSchedule {

    @Resource
    private ModbusServerService modbusServerService;

    @Resource
    private IEC104ServerService iec104ServerService;

    @Scheduled(initialDelay = 5000, fixedRate = 1000)
    public void schedule() {
        // long startTime = System.currentTimeMillis();
        // log.info("开始置数: {}", System.currentTimeMillis());
        // 1. 读取modbus数据(一般而言只需要读取线圈和保持寄存器即可，这里我全部读取了)
        readModbusData();
        // 2. 根据公式计算所有的数据
        calculate();
        // 3. 将计算的数据写入input和输入寄存器
        writeInputAndInputRegister();
        // 4. 将遥信与遥测数据通知客户端
        noticeYXAndYC();
        // log.info("置数完成: {}  {}", System.currentTimeMillis(), System.currentTimeMillis() - startTime);
    }

    private void noticeYXAndYC() {
        for (ServerEntity serverEntity : GlobalVariable.SERVER_LIST) {
            if (serverEntity.getServerType().equals(ServerType.IEC104)) {
                for (DataEntity listDatum : serverEntity.getListData()) {
                    // 不需要变更的数据点不进行数据变更
                    if (listDatum.getUpdateEnable().equals(EnableEnum.NotEnabled)) {
                        continue;
                    }
                    if (listDatum.getCategory().equals(DataCategoryEnum.YX)) {
                        iec104ServerService.broadYXValues(serverEntity.getIEC104Server(), listDatum,
                                GlobalVariable.GLOBAL_MAP.get(serverEntity.getPort() + ":" + listDatum.getKey()) == 1.0f);
                    } else if (listDatum.getCategory().equals(DataCategoryEnum.YC)) {
                        iec104ServerService.broadYCValues(serverEntity.getIEC104Server(), listDatum,
                                GlobalVariable.GLOBAL_MAP.get(serverEntity.getPort() + ":" + listDatum.getKey()));
                    }
                }
            }
        }
    }

    private void writeInputAndInputRegister() {
        for (ServerEntity serverEntity : GlobalVariable.SERVER_LIST) {
            if (serverEntity.getServerType().equals(ServerType.MODBUS)) {
                if (serverEntity.getModbusServerSet() == null) {
                    continue;
                }
                for (DataEntity listDatum : serverEntity.getListData()) {
                    // 某些数据点不变更，则不进行数据回写。
                    if (listDatum.getUpdateEnable().equals(EnableEnum.NotEnabled)) {
                        continue;
                    }
                    if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.INPUT)) {
                        modbusServerService.writeInput(serverEntity, listDatum,
                                GlobalVariable.GLOBAL_MAP.get(serverEntity.getPort() + ":" + listDatum.getKey()) == 1.0f);
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.COIL)) {
                        modbusServerService.writeCoil(serverEntity, listDatum,
                                GlobalVariable.GLOBAL_MAP.get(serverEntity.getPort() + ":" + listDatum.getKey()) == 1.0f);
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.INPUT_REGISTER)) {
                        modbusServerService.writeInputRegister(serverEntity, listDatum,
                                GlobalVariable.GLOBAL_MAP.getOrDefault(serverEntity.getPort() + ":" + listDatum.getKey(), 1.0f));
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.HOLD_REGISTER)) {
                        modbusServerService.writeHoldRegister(serverEntity, listDatum,
                                GlobalVariable.GLOBAL_MAP.getOrDefault(serverEntity.getPort() + ":" + listDatum.getKey(), 1.0f));
                    } else {
                        log.error("Unknown modbus register {}", listDatum.getModbusRegisterEnum());
                    }
                }
            }
        }
    }

    private void calculate() {
        for (ServerEntity serverEntity : GlobalVariable.SERVER_LIST) {
            for (DataEntity listDatum : serverEntity.getListData()) {
                Float v = 1.0f;
                if (StringUtils.isBlank(listDatum.getCalculationFormula())) {
                    /**
                     * 1. 初始化值只在第一次程序启动的时候，计算加载数据到缓存；
                     * 2. 如果公式为空，则使用缓存的值。比如：遥调通常初始化值为0，当agvc下发指令后才有值在缓存。
                     * 3. 如果有偏差，记得配置公式，不然始终使用缓存的值进行偏差，可能会越来越小。
                     */
                    v = GlobalVariable.GLOBAL_MAP.get(serverEntity.getPort() + ":" + listDatum.getKey());
                } else {
                    v = FormulaCalculationUtil.getFormulaResult(serverEntity.getTableName(), listDatum.getCalculationFormula());
                }
                float rand = 0.0f;
                if (listDatum.getDeviation() > 0) {
                    rand = (float) ThreadLocalRandom.current().nextDouble(listDatum.getDeviation() * -1, listDatum.getDeviation());
                }
                GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":" + listDatum.getKey(), v + rand);
            }
        }
    }

    private void readModbusData() {
        for (ServerEntity serverEntity : GlobalVariable.SERVER_LIST) {
            if (serverEntity.getServerType().equals(ServerType.MODBUS)) {
                if (serverEntity.getModbusServerSet() == null) {
                    continue;
                }
                for (DataEntity listDatum : serverEntity.getListData()) {
                    Float v = 1.0f;
                    if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.COIL)) {
                        Float read = modbusServerService.readCoil(serverEntity, listDatum);
                        GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":" + listDatum.getKey(), read);
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.INPUT)) {
                        Float read = modbusServerService.readInput(serverEntity, listDatum);
                        GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":" + listDatum.getKey(), read);
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.HOLD_REGISTER)) {
                        Float read = modbusServerService.readHoldRegister(serverEntity, listDatum);
                        GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":" + listDatum.getKey(), read);
                    } else if (listDatum.getModbusRegisterEnum().equals(ModbusRegisterEnum.INPUT_REGISTER)) {
                        Float read = modbusServerService.readInputRegister(serverEntity, listDatum);
                        GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":" + listDatum.getKey(), read);
                    } else {
                        log.warn("未知数据，tableName: {}, data: {}", serverEntity.getTableName(), listDatum);
                    }
                }
            }
            if (serverEntity.getInstalledCapacity() != 0.0f) {
                // 如果是EMS，将装机容量整到缓存
                GlobalVariable.GLOBAL_MAP.put(serverEntity.getPort() + ":InstalledCapacity", serverEntity.getInstalledCapacity());
            }
        }
    }

}
